﻿using System;
using UnityEngine;

namespace IQIGame.Onigao.Game
{
    /// <summary>
    /// 类名 : 列表或者滚动的非循环列表
    /// 作者 : Canyon / 龚阳辉
    /// 日期 : 2024-05-20 09:45
    /// 功能 : 
    /// </summary>
    /// <typeparam name="T">UIBaseNode</typeparam>
    public class ListScrollAdapter<T> : IUIList where T : UIBaseNode, new()
    {
        public int totalCount { get; private set; } = -1;
        // 必选项，刷新复用的item用
        private Action<T, int> callIUnitChanged;
        private UIItemPool<T> poolItem = null;
        private UIBaseWindow belongWindow = null;
        private GameObject gobjRoot = null;
        private bool isRootActive = false;

        private ListUnitMappingData<T> dataMapping;
        private ListUnitSelect<T> unitSelect;
        private ListUnitUpdate<T> unitUpdate;
        public UnitSelectType selectedType { get => unitSelect.selectedType; set => unitSelect.selectedType = value; }
        public int selectedIndex => unitSelect.selectedIndex;

        public ListScrollAdapter(GameObject cellGo, UIBaseWindow baseWindow)
        {
            this.gobjRoot = cellGo.transform.parent?.gameObject;
            this.isRootActive = this.gobjRoot?.activeSelf ?? false;
            this.belongWindow = baseWindow;

            this.poolItem = new UIItemPool<T>(cellGo, baseWindow);
            this.dataMapping = new ListUnitMappingData<T>(4);
        }

        public ListScrollAdapter<T> BindUnitChangedCall(Action<T, int> funcChanged)
        {
            this.callIUnitChanged = funcChanged;
            return this;
        }

        public ListScrollAdapter<T> InitUnitSelected(UnitSelectType selectedType, Action<int, T> funcSelected, Action<int, T> funcUnSelected = null)
        {
            return InitUnitSelected(new ListUnitSelect<T>.UnitSelectData()
            {
                selectedType = selectedType,
                callSelected = funcSelected,
                callUnSelected = funcUnSelected,
            });
        }

        public ListScrollAdapter<T> InitUnitSelected(ListUnitSelect<T>.UnitSelectData data)
        {
            if (this.unitSelect == null)
            {
                this.unitSelect = new ListUnitSelect<T>(this.dataMapping);
                this.unitSelect.Initialize(data);
            }
            return this;
        }

        public ListScrollAdapter<T> SetUnitMitiSelect(int maxSelected, Action funcFullWhenSelectOther = null)
        {
            if (this.unitSelect != null)
            {
                this.unitSelect.SetMitiSelect(maxSelected, funcFullWhenSelectOther);
            }
            return this;
        }

        public ListScrollAdapter<T> InitUnitUpdate()
        {
            if (this.unitUpdate == null)
            {
                this.unitUpdate = new ListUnitUpdate<T>(this.dataMapping);
                this.unitUpdate.AddUpdate();
            }
            return this;
        }

        public void RefillCells(int totalCount, int selectIndex = -1)
        {
            this.SetActive(true);
            this.totalCount = totalCount;
            this.dataMapping.EmptyMapping();
            this.unitSelect?.ReIniteListUnits();
            this.poolItem.HideAfter(totalCount);

            T item = null;
            for (int i = 0; i < totalCount; i++)
            {
                item = this.poolItem.GetActiveOne(i);
                if (item == null)
                    item = this.poolItem.GetOne(false);
                this.OnCreateItem(item, i);
                this.OnItemDataChange(item, i);
                this.OnInitSelected(item, i);
            }

            this.unitSelect?.ComplateIniteListUnits();
            ResetSelected(selectIndex);
        }

        private void OnCreateItem(T node, int index)
        {
            this.dataMapping.InitTUnitMapping(node);
            this.dataMapping.InitIndexMapping(node, index);
        }

        private void OnInitSelected(T node, int index)
        {
            this.unitSelect?.Refresh(node, index);
        }

        private void OnItemDataChange(T node, int index)
        {
            callIUnitChanged?.Invoke(node, index);
        }

        public void ResetSelected(int selectIndex)
        {
            this.unitSelect?.SetSelected(selectIndex, true);
        }

        public T GetTEntity(int index)
        {
            return this.dataMapping.GetTEntity(index);
        }

        public void SetActive(bool isActive)
        {
            if (this.isRootActive != isActive)
            {
                this.isRootActive = isActive;
                this.gobjRoot?.SetActive(isActive);
            }
        }

        public void RefreshCells()
        {
            var activeUnits = this.dataMapping.GetActiveUnits();
            foreach (var unit in activeUnits)
            {
                if (this.dataMapping.TryGetIndex(unit.gameObject, out var index))
                {
                    this.OnItemDataChange(unit, index);
                }
            }
        }

        public void Clear()
        {
            this.totalCount = -1;
            this.callIUnitChanged = null;
            this.belongWindow = null;
            this.gobjRoot = null;
            this.isRootActive = false;

            this.unitSelect?.Clear();
            this.unitSelect = null;
            this.dataMapping?.ClearExcludeUnits();
            this.dataMapping = null;
            this.unitUpdate?.Clear();
            this.unitUpdate = null;
            this.poolItem?.Clear();
            this.poolItem = null;
        }
    }
}
